package org.atlantis.grosbeak.castor.defaults;

import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import org.atlantis.grosbeak.castor.Castor;
import org.atlantis.grosbeak.castor.Castors;
import org.atlantis.grosbeak.castor.FailToCastException;
import org.atlantis.grosbeak.lang.Exceptions;

@SuppressWarnings("unchecked")
public class CollectionToArray implements Castor<Collection, Object> {

	public Type getFrom() {
		return Collection.class;
	}

	public Type getTo() {
		return Array.class;
	}

	public Object obverseCast(Collection src, Class<?> toType)
			throws FailToCastException {
		Class<?> compType = toType.getComponentType();
		Object arr = Array.newInstance(compType, src.size());
		int i = 0;
		for (Iterator iter = src.iterator(); iter.hasNext();) {
			Array.set(arr, i++, Castors.me().castTo(iter.next(), compType));
		}
		return arr;
	}

	public Collection reverseCast(Object src, Class<?> toType)
			throws FailToCastException {
		Collection coll = null;
		try {
			coll = (Collection<Object>) toType.newInstance();
		} catch (Exception e) {
			if (Modifier.isAbstract(toType.getModifiers())
					&& toType.isAssignableFrom(Array.class)) {
				coll = new ArrayList<Object>(Array.getLength(src));
			}
			if (null == coll)
				throw Exceptions.makeThrow(FailToCastException.class,
						"Unable to implement '%s'.", toType.getName());
		}
		for (int i = 0; i < Array.getLength(src); i++) {
			coll.add(Array.get(src, i));
		}
		return coll;
	}
}
